﻿using System;
using System.Globalization;

namespace RTools_NTS.Util
{
	public abstract class Token
	{
		public int LineNumber
		{
			get
			{
				return this._lineNumber;
			}
		}

		public object Object
		{
			get
			{
				return this.obj;
			}
		}

		public bool UntermError
		{
			get
			{
				return this.untermError;
			}
			set
			{
				this.untermError = value;
			}
		}

		public string UntermErrorMsg
		{
			get
			{
				return this.untermErrorMsg;
			}
			set
			{
				this.untermError = true;
				this.untermErrorMsg = value;
			}
		}

		public Token(int line)
		{
			this.obj = null;
			this.untermError = false;
			this._lineNumber = line;
		}

		public override bool Equals(object other)
		{
			return other != null && other is Token && this.obj.Equals(((Token)other).obj);
		}

		public bool Equals(string s)
		{
			return s != null && this.StringValue.Equals(s);
		}

		public bool Equals(char c)
		{
			return this is CharToken && (this as CharToken).Object.Equals(c);
		}

		public static bool operator ==(Token t, object o)
		{
			if (t == null)
			{
				return o == null;
			}
			return o != null && t.Equals(o);
		}

		public static bool operator !=(Token t, object o)
		{
			if (t == null)
			{
				return o != null;
			}
			return !t.Equals(o);
		}

		public static bool operator ==(Token t, char c)
		{
			return t != null && t.Equals(c);
		}

		public static bool operator !=(Token t, char c)
		{
			return t != null && !t.Equals(c);
		}

		public static bool operator ==(Token t, string s)
		{
			if (t == null)
			{
				return s == null;
			}
			return t.Equals(s);
		}

		public static bool operator !=(Token t, string s)
		{
			if (t == null)
			{
				return s != null;
			}
			return !t.Equals(s);
		}

		public override int GetHashCode()
		{
			return this.ToString().GetHashCode();
		}

		public virtual string StringValue
		{
			get
			{
				return "unset";
			}
		}

		public string ToLineString()
		{
			return string.Format("{0}: line {1}", this.ToDebugString(), this._lineNumber);
		}

		public virtual string ToDebugString()
		{
			return string.Format("{0}: line {1}", this.ToString(), this._lineNumber);
		}

		public object ConvertToType(Type t)
		{
			return Convert.ChangeType(this.StringValue, t, CultureInfo.InvariantCulture);
		}

		private readonly int _lineNumber;

		protected object obj;

		private bool untermError;

		private string untermErrorMsg;
	}
}
